package com.example.alibabavodossservice.vod.decrypt;

import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.http.ProtocolType;
import com.aliyuncs.vod.model.v20170321.DecryptKMSDataKeyRequest;
import com.aliyuncs.vod.model.v20170321.DecryptKMSDataKeyResponse;
import com.sun.net.httpserver.Headers;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
import com.sun.net.httpserver.spi.HttpServerProvider;
import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.URI;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static com.berrontech.docuhub.media.help.vod.InitVODConstants.VOD_CLIENT;

/**
 * 描述信息： hls解密处理程序
 *
 * @author xugenyin
 * 创建日期 2023/09/28
 */

@Component
public class HlsDecryptServer implements HttpHandler {

    private static final Logger LOGGER = LoggerFactory.getLogger(HlsDecryptServer.class);

    @Bean
    public HlsDecryptServer hlsDecryptHandler() {
        HlsDecryptServer server = new HlsDecryptServer();
        try {
            server.serviceBootStrap();
            LOGGER.info("启动阿里云播放器解密程序");
        } catch (IOException e) {
            e.printStackTrace();
        }
        return server;
    }


    /**
     * 处理请求
     *
     * @param httpExchange http交换
     *                     <p>
     *                     2023/09/28
     */
    public void handle(HttpExchange httpExchange) throws IOException {
        String requestMethod = httpExchange.getRequestMethod();
        if ("GET".equalsIgnoreCase(requestMethod)) {
            //校验token的有效性
            String token = getMtsHlsUriToken(httpExchange);
            System.out.println("token: " + token);
            boolean validRe = validateToken(token);
            if (!validRe) {
                return;
            }
            //从URL中取得密文密钥
            String ciphertext = getCiphertext(httpExchange);
            if (null == ciphertext) {
                return;
            }
            //从KMS中解密出来，并Base64 decode
            byte[] key = decrypt(ciphertext);
            //设置header
            assert key != null;
            setHeader(httpExchange, key);
            //返回Base64 decode之后的密钥
            OutputStream responseBody = httpExchange.getResponseBody();
            responseBody.write(key);
            responseBody.close();
        }
    }

    /**
     * 设置头部信息
     *
     * @param httpExchange http交换
     * @param key          钥匙
     *                     <p>
     *                     2023/09/28
     */
    private void setHeader(HttpExchange httpExchange, byte[] key) throws IOException {
        Headers responseHeaders = httpExchange.getResponseHeaders();
        responseHeaders.set("Access-Control-Allow-Origin", "*");
        httpExchange.sendResponseHeaders(HttpURLConnection.HTTP_OK, key.length);
    }

    /**
     * 调用KMS decrypt接口解密，并将明文Base64 decode
     *
     * @param ciphertext 密文密钥
     * @return 明文密钥
     */
    private byte[] decrypt(String ciphertext) {
        DecryptKMSDataKeyRequest request = new DecryptKMSDataKeyRequest();
        request.setCipherText(ciphertext);
        request.setProtocol(ProtocolType.HTTPS);
        try {
            DecryptKMSDataKeyResponse response = VOD_CLIENT.getAcsResponse(request);
            String plaintext = response.getPlaintext();
            System.out.println("PlainText: " + plaintext);
            //注意：需要Base64 decode
            return Base64.decodeBase64(plaintext);
        } catch (ClientException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 校验令牌有效性
     *
     * @param token 令牌
     * @return 有效性
     */
    private boolean validateToken(String token) {
        return null != token && !"".equals(token);
        //TODO 业务方实现令牌有效性校验
    }

    /**
     * 从URL中获取密文密钥参数
     *
     * @param httpExchange httpExchange
     * @return 密文密钥
     */
    private String getCiphertext(HttpExchange httpExchange) {
        URI uri = httpExchange.getRequestURI();
        String queryString = uri.getQuery();
        String pattern = "CipherText=(\\w*)";
        Pattern r = Pattern.compile(pattern);
        Matcher m = r.matcher(queryString);
        if (m.find()) {
            return m.group(1);
        } else {
            System.out.println("Not Found CipherText Param");
            return null;
        }
    }

    /**
     * 获取Token参数
     *
     * @param httpExchange httpExchange
     * @return Token
     */
    private String getMtsHlsUriToken(HttpExchange httpExchange) {
        URI uri = httpExchange.getRequestURI();
        String queryString = uri.getQuery();
        String pattern = "MtsHlsUriToken=(\\w*)";
        Pattern r = Pattern.compile(pattern);
        Matcher m = r.matcher(queryString);
        if (m.find()) {
            return m.group(1);
        } else {
            System.out.println("Not Found MtsHlsUriToken Param");
            return null;
        }
    }

    /**
     * 服务启动
     */
    public void serviceBootStrap() throws IOException {
        HttpServerProvider provider = HttpServerProvider.provider();
        //监听端口可以自定义，能同时接受最多30个请求
        HttpServer httpserver = provider.createHttpServer(new InetSocketAddress(8099), 30);
        httpserver.createContext("/", new HlsDecryptServer());
        httpserver.start();
    }
}
